๐ŸŒฑ Summary

This document presents a comprehensive case of an IoT-based Smart Agriculture System designed for a coffee farm. The system uses real-time sensors and automated irrigation to optimize water usage and increase crop yield.

Main Objectives

  • ๐Ÿ“Š Work with 30 days of IoT sensor data
  • ๐Ÿ’ง Implement smart irrigation control algorithm
  • ๐Ÿ“ˆ Analyze system performance and efficiency
  • ๐ŸŽฏ Demonstrate ROI and sustainability benefits

required_packages <- c("dplyr", "lubridate", "plotly", 
                      "DT", "kableExtra", "corrplot", "scales")

for(pkg in required_packages) {
  if(!require(pkg, character.only = TRUE)) {
    install.packages(pkg)
    library(pkg, character.only = TRUE)
  }
}
set.seed(123)

๐Ÿ”งParameters

#configuration
DURATION_DAYS <- 30
INTERVAL_MINUTES <- 5
READINGS_PER_DAY <- (24 * 60) / INTERVAL_MINUTES
TOTAL_READINGS <- DURATION_DAYS * READINGS_PER_DAY

# Sensor parameters
TEMP_BASE <- 25        # Base temperature (ยฐC)
TEMP_NOISE <- 2.5      # Temperature noise
HUMIDITY_BASE <- 65    # Base humidity (%)
HUMIDITY_NOISE <- 5    # Humidity noise
SOIL_BASE <- 1500      # Base soil moisture
SOIL_NOISE <- 50       # Soil moisture noise
LIGHT_BASE <- 500      # Base light intensity
LIGHT_NOISE <- 100     # Light noise

# Irrigation thresholds
DRY_THRESHOLD <- 1800  # Activate irrigation above this
WET_THRESHOLD <- 1200  # Optimal moisture below this
IRRIGATION_EFFECT <- 200  # Moisture reduction per irrigation
WATER_PER_CYCLE <- 5   # Liters per irrigation cycle

๐ŸŽฒ Data

simulate_daily_pattern <- function(hour) {
  # Temperature peaks at 14:00
  temp_variation <- 5 * sin((hour - 6) * pi / 12)
  
  # Light is high between 6:00 and 18:00
  light_variation <- ifelse(
    hour >= 6 & hour <= 18,
    800 * sin((hour - 6) * pi / 12),
    -400
  )
  
  return(list(temp = temp_variation, light = light_variation))
}

# Function to generate rain events
generate_rain_events <- function(n_readings) {
  rain <- rep(0, n_readings)
  n_events <- sample(3:8, 1)
  
  for(i in 1:n_events) {
    start <- sample(1:(n_readings - 20), 1)
    duration <- sample(5:20, 1)
    intensity <- runif(1, 50, 200)
    rain[start:(start + duration - 1)] <- intensity
  }
  
  return(rain)
}

# Irrigation control logic
should_irrigate <- function(soil_moisture, rain_intensity) {
  if(rain_intensity > 0) return(FALSE)
  if(soil_moisture < WET_THRESHOLD) return(FALSE)
  if(soil_moisture > DRY_THRESHOLD) return(TRUE)
  return(FALSE)
}

##Complete Dataset

cat("๐Ÿ”„ IoT sensor data...\n")
## ๐Ÿ”„ IoT sensor data...
# Initialize timestamp
start_time <- as.POSIXct("2024-01-01 00:00:00")
timestamps <- start_time + minutes(seq(0, TOTAL_READINGS - 1) * INTERVAL_MINUTES)

# Generate rain events
rainfall <- generate_rain_events(TOTAL_READINGS)

# Initialize vectors
temperature <- numeric(TOTAL_READINGS)
humidity <- numeric(TOTAL_READINGS)
soil_moisture <- numeric(TOTAL_READINGS)
light_intensity <- numeric(TOTAL_READINGS)
irrigation <- numeric(TOTAL_READINGS)

for(i in 1:TOTAL_READINGS) {
  hour <- hour(timestamps[i]) + minute(timestamps[i]) / 60
  
  # Get daily patterns
  patterns <- simulate_daily_pattern(hour)
  
  #sensor readings
  temperature[i] <- TEMP_BASE + patterns$temp + rnorm(1, 0, TEMP_NOISE)
  humidity[i] <- HUMIDITY_BASE - patterns$temp * 2 + rnorm(1, 0, HUMIDITY_NOISE)
  light_intensity[i] <- max(0, LIGHT_BASE + patterns$light + rnorm(1, 0, LIGHT_NOISE))
  
  # Soil moisture affected by rain
  rain_effect <- -rainfall[i] * 0.3
  soil_base <- SOIL_BASE + i * 0.5 + rnorm(1, 0, SOIL_NOISE) + rain_effect
  
  # Apply irrigation if needed
  irrigate <- should_irrigate(soil_base, rainfall[i])
  if(irrigate) {
    soil_base <- soil_base - IRRIGATION_EFFECT
  }
  
  soil_moisture[i] <- max(0, soil_base)
  irrigation[i] <- as.numeric(irrigate)
}

# Create dataframe
iot_data <- tibble(
  timestamp = timestamps,
  temperature = temperature,
  humidity = humidity,
  soil_moisture = soil_moisture,
  light_intensity = light_intensity,
  rainfall = rainfall,
  irrigation = irrigation,
  day = day(timestamps),
  hour = hour(timestamps)
)

cat("โœ… Data gomplete!\n")
## โœ… Data gomplete!
cat(sprintf("๐Ÿ“Š  %d readings\n", nrow(iot_data)))
## ๐Ÿ“Š  8640 readings

๐Ÿ“Š Data Overview

# Display first few rows
iot_data %>%
  head(20) %>%
  mutate(across(where(is.numeric), ~round(., 2))) %>%
  DT::datatable(
    options = list(
      pageLength = 10,
      scrollX = TRUE,
      dom = 'Bfrtip'
    ),
    caption = "Table 1: First 20 Sensor Readings"
  )

Summary Statistics

summary_stats <- iot_data %>%
  select(temperature, humidity, soil_moisture, light_intensity) %>%
  summary()

kable(summary_stats, caption = "Table 2: Sensor Data Summary Statistics") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Table 2: Sensor Data Summary Statistics
temperature humidity soil_moisture light_intensity
Min. :12.49 Min. :37.75 Min. :1393 Min. : 0.0
1st Qu.:21.61 1st Qu.:58.42 1st Qu.:2379 1st Qu.: 103.0
Median :24.99 Median :64.95 Median :3461 Median : 401.4
Mean :24.97 Mean :65.04 Mean :3475 Mean : 558.7
3rd Qu.:28.28 3rd Qu.:71.62 3rd Qu.:4546 3rd Qu.:1044.3
Max. :38.30 Max. :91.52 Max. :5740 Max. :1584.3

๐Ÿ“ˆ Performance Analysis

Key Performance Indicators

# Calculate KPIs
total_irrigations <- sum(iot_data$irrigation)
irrigation_hours <- (total_irrigations * INTERVAL_MINUTES) / 60
water_used <- total_irrigations * WATER_PER_CYCLE
water_per_day <- water_used / DURATION_DAYS

# Soil moisture analysis
optimal_readings <- sum(iot_data$soil_moisture >= WET_THRESHOLD & 
                       iot_data$soil_moisture <= DRY_THRESHOLD)
optimal_percentage <- (optimal_readings / TOTAL_READINGS) * 100

dry_readings <- sum(iot_data$soil_moisture > DRY_THRESHOLD)
wet_readings <- sum(iot_data$soil_moisture < WET_THRESHOLD)

dry_percentage <- (dry_readings / TOTAL_READINGS) * 100
wet_percentage <- (wet_readings / TOTAL_READINGS) * 100

# Rain statistics
rain_events <- sum(iot_data$rainfall > 0)
total_rainfall <- sum(iot_data$rainfall)

# Efficiency score
efficiency_score <- optimal_percentage
11.7%
System Efficiency Score
7990
Total Irrigations
3.995^{4}L
Total Water Used
1331.7L
Water per Day

Performance

performance_data <- tibble(
  Metric = c(
    "Total Irrigation Activations",
    "Irrigation Time (hours)",
    "Water Consumed (liters)",
    "Average Water per Day (L/day)",
    "Time in Optimal Range",
    "Time Too Dry",
    "Time Too Wet",
    "Number of Rain Events",
    "Total Rainfall (units)",
    "Overall Efficiency Score"
  ),
  Value = c(
    total_irrigations,
    round(irrigation_hours, 2),
    round(water_used, 2),
    round(water_per_day, 2),
    paste0(round(optimal_percentage, 2), "%"),
    paste0(round(dry_percentage, 2), "%"),
    paste0(round(wet_percentage, 2), "%"),
    rain_events,
    round(total_rainfall, 2),
    paste0(round(efficiency_score, 2), "%")
  ),
  Status = c(
    "โœ…", "โœ…", "โœ…", "โœ…",
    ifelse(optimal_percentage > 70, "โœ…", "โš ๏ธ"),
    ifelse(dry_percentage < 15, "โœ…", "โš ๏ธ"),
    ifelse(wet_percentage < 15, "โœ…", "โš ๏ธ"),
    "โ„น๏ธ", "โ„น๏ธ",
    ifelse(efficiency_score > 70, "โœ…", "โš ๏ธ")
  )
)

kable(performance_data, caption = "Table 3: System Performance Metrics") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed")) %>%
  column_spec(3, bold = TRUE)
Table 3: System Performance Metrics
Metric Value Status
Total Irrigation Activations 7990 โœ… |
Irrigation Time (hours) 665.83 โœ… |
Water Consumed (liters) 39950 โœ… |
Average Water per Day (L/day) 1331.67 โœ… |
Time in Optimal Range 11.72% โš ๏ธ
Time Too Dry 88.28% โš ๏ธ
Time Too Wet 0% โœ… |
Number of Rain Events 50 โ„น๏ธ
Total Rainfall (units) 8094 โ„น๏ธ
Overall Efficiency Score 11.72% โš ๏ธ
if(efficiency_score > 80) {
  cat('<div class="alert alert-success">')
  cat('<strong>โœ… Excellent Performance!</strong><br>')
  cat('The system maintains optimal soil moisture over 80% of the time.')
  cat('</div>')
} else if(efficiency_score > 60) {
  cat('<div class="alert alert-warning">')
  cat('<strong>โš ๏ธ Good Performance</strong><br>')
  cat('The system performs well but has room for optimization.')
  cat('</div>')
} else {
  cat('<div class="alert alert-warning">')
  cat('<strong>โŒ Needs Optimization</strong><br>')
  cat('Consider adjusting irrigation thresholds or sensor calibration.')
  cat('</div>')
}
## <div class="alert alert-warning"><strong>โŒ Needs Optimization</strong><br>Consider adjusting irrigation thresholds or sensor calibration.</div>

๐Ÿ“‰ Visualizations

Soil Moisture with Control Thresholds

p2 <- iot_data %>%
  ggplot(aes(x = timestamp, y = soil_moisture)) +
  geom_line(color = "#8B4513", linewidth = 0.8) +
  geom_hline(yintercept = DRY_THRESHOLD, color = "#e74c3c", 
             linetype = "dashed", linewidth = 1) +
  geom_hline(yintercept = WET_THRESHOLD, color = "#27ae60", 
             linetype = "dashed", linewidth = 1) +
  geom_ribbon(aes(ymin = WET_THRESHOLD, ymax = DRY_THRESHOLD), 
              alpha = 0.2, fill = "#27ae60") +
  annotate("text", x = min(iot_data$timestamp), y = DRY_THRESHOLD + 50, 
           label = "Dry Threshold", color = "#e74c3c", hjust = 0) +
  annotate("text", x = min(iot_data$timestamp), y = WET_THRESHOLD - 50, 
           label = "Wet Threshold", color = "#27ae60", hjust = 0) +
  annotate("text", x = min(iot_data$timestamp), y = (DRY_THRESHOLD + WET_THRESHOLD) / 2, 
           label = "Optimal Range", color = "#27ae60", hjust = 0, fontface = "bold") +
  labs(
    title = "Soil Moisture with Irrigation Control Thresholds",
    x = "Time",
    y = "Soil Moisture Level"
  ) +
  theme_minimal() +
  theme(plot.title = element_text(size = 16, face = "bold"))

ggplotly(p2)

Irrigation Activity and Rainfall

p3 <- iot_data %>%
  ggplot(aes(x = timestamp)) +
  geom_area(aes(y = irrigation * 100, fill = "Irrigation"), alpha = 0.6) +
  geom_col(aes(y = rainfall / 2, fill = "Rainfall"), alpha = 0.7, width = 0.1) +
  scale_fill_manual(values = c("Irrigation" = "#3498db", "Rainfall" = "#2980b9")) +
  labs(
    title = "Irrigation Activity and Rainfall Events",
    x = "Time",
    y = "Intensity",
    fill = "Event Type"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(size = 16, face = "bold"),
    legend.position = "top"
  )

ggplotly(p3)

Light Intensity Pattern

p4 <- iot_data %>%
  ggplot(aes(x = timestamp, y = light_intensity)) +
  geom_area(fill = "#f39c12", alpha = 0.6) +
  labs(
    title = "Light Intensity Over Time",
    x = "Time",
    y = "Light Intensity (lux)"
  ) +
  theme_minimal() +
  theme(plot.title = element_text(size = 16, face = "bold"))

ggplotly(p4)

Daily Patterns

daily_avg <- iot_data %>%
  group_by(hour) %>%
  summarise(
    avg_temp = mean(temperature),
    avg_humidity = mean(humidity),
    avg_soil = mean(soil_moisture),
    avg_light = mean(light_intensity)
  )

p5 <- daily_avg %>%
  ggplot(aes(x = hour)) +
  geom_line(aes(y = avg_temp * 50, color = "Temperature"), linewidth = 1.2) +
  geom_line(aes(y = avg_humidity * 20, color = "Humidity"), linewidth = 1.2) +
  geom_line(aes(y = avg_soil, color = "Soil Moisture"), linewidth = 1.2) +
  scale_color_manual(values = c(
    "Temperature" = "#e74c3c",
    "Humidity" = "#3498db",
    "Soil Moisture" = "#8B4513"
  )) +
  labs(
    title = "Average Daily Patterns",
    x = "Hour of Day",
    y = "Scaled Values",
    color = "Sensor"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(size = 16, face = "bold"),
    legend.position = "top"
  )

ggplotly(p5)

Correlation Matrix

cor_data <- iot_data %>%
  select(temperature, humidity, soil_moisture, light_intensity, rainfall)

cor_matrix <- cor(cor_data)

corrplot(cor_matrix, 
         method = "color",
         type = "upper",
         addCoef.col = "black",
         tl.col = "black",
         tl.srt = 45,
         title = "Sensor Data Correlations",
         mar = c(0, 0, 2, 0))

Soil Moisture Distribution

p6 <- iot_data %>%
  ggplot(aes(x = soil_moisture)) +
  geom_histogram(bins = 50, fill = "#8B4513", alpha = 0.7, color = "black") +
  geom_vline(xintercept = DRY_THRESHOLD, color = "#e74c3c", 
             linetype = "dashed", linewidth = 1.2) +
  geom_vline(xintercept = WET_THRESHOLD, color = "#27ae60", 
             linetype = "dashed", linewidth = 1.2) +
  annotate("rect", xmin = WET_THRESHOLD, xmax = DRY_THRESHOLD, 
           ymin = 0, ymax = Inf, alpha = 0.2, fill = "#27ae60") +
  labs(
    title = "Distribution of Soil Moisture Levels",
    subtitle = "Optimal range highlighted in green",
    x = "Soil Moisture Level",
    y = "Frequency"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(size = 16, face = "bold"),
    plot.subtitle = element_text(size = 12)
  )

ggplotly(p6)

๐Ÿ’ฐ Cost-Benefit Analysis

# Traditional vs IoT system comparison
traditional_water <- 150  # liters per day
iot_water <- water_per_day

water_savings_percent <- ((traditional_water - iot_water) / traditional_water) * 100
water_cost_per_liter <- 0.05  # USD
daily_water_savings <- (traditional_water - iot_water) * water_cost_per_liter
annual_water_savings <- daily_water_savings * 365

# Labor savings
traditional_labor_hours <- 2  # hours per day
iot_labor_hours <- 0.5
labor_cost_per_hour <- 3  # USD
daily_labor_savings <- (traditional_labor_hours - iot_labor_hours) * labor_cost_per_hour
annual_labor_savings <- daily_labor_savings * 365

# System cost
system_cost <- 180  # USD
annual_maintenance <- 30  # USD

# Total savings
total_annual_savings <- annual_water_savings + annual_labor_savings - annual_maintenance
roi_months <- system_cost / (total_annual_savings / 12)

cost_benefit_data <- tibble(
  Category = c(
    "Water Consumption (L/day)",
    "Water Cost Savings ($/day)",
    "Labor Time (hours/day)",
    "Labor Cost Savings ($/day)",
    "Annual Water Savings ($)",
    "Annual Labor Savings ($)",
    "Annual Maintenance Cost ($)",
    "Total Annual Net Savings ($)",
    "System Cost ($)",
    "ROI Period (months)"
  ),
  Traditional = c(
    traditional_water, NA, traditional_labor_hours, NA, NA, NA, NA, NA, NA, NA
  ),
  IoT_System = c(
    round(iot_water, 2),
    round(daily_water_savings, 2),
    iot_labor_hours,
    round(daily_labor_savings, 2),
    round(annual_water_savings, 2),
    round(annual_labor_savings, 2),
    annual_maintenance,
    round(total_annual_savings, 2),
    system_cost,
    round(roi_months, 1)
  ),
  Improvement = c(
    paste0(round(water_savings_percent, 1), "%"),
    paste0("+$", round(daily_water_savings, 2)),
    paste0(round((traditional_labor_hours - iot_labor_hours) / traditional_labor_hours * 100, 1), "%"),
    paste0("+$", round(daily_labor_savings, 2)),
    paste0("+$", round(annual_water_savings, 2)),
    paste0("+$", round(annual_labor_savings, 2)),
    paste0("-$", annual_maintenance),
    paste0("+$", round(total_annual_savings, 2)),
    "-",
    paste0(round(roi_months, 1), " months")
  )
)


cost_benefit_data
## # A tibble: 10 ร— 4
##    Category                     Traditional IoT_System Improvement
##    <chr>                              <dbl>      <dbl> <chr>      
##  1 Water Consumption (L/day)            150     1332.  -787.8%    
##  2 Water Cost Savings ($/day)            NA      -59.1 +$-59.08   
##  3 Labor Time (hours/day)                 2        0.5 75%        
##  4 Labor Cost Savings ($/day)            NA        4.5 +$4.5      
##  5 Annual Water Savings ($)              NA   -21565.  +$-21565.42
##  6 Annual Labor Savings ($)              NA     1642.  +$1642.5   
##  7 Annual Maintenance Cost ($)           NA       30   -$30       
##  8 Total Annual Net Savings ($)          NA   -19953.  +$-19952.92
##  9 System Cost ($)                       NA      180   -          
## 10 ROI Period (months)                   NA       -0.1 -0.1 months

๐Ÿ’ฐ Financial Impact
The IoT system pays for itself in approximately -0.1 months through water and labor savings. Annual net savings of $-1.995292^{4} represent a significant improvement in farm profitability.


๐ŸŽฏ Conclusions and Recommendations

Key Findings

  1. System Efficiency: The IoT system maintains optimal soil moisture 11.7% of the time.

  2. Water Conservation: Achieved -787.8% reduction in water consumption compared to traditional methods.

  3. Labor Efficiency: Reduced manual labor by 75%.

  4. ROI: System investment recovers in -0.1 months.

Recommendations

For Optimal Performance:

  • โœ… Maintain sensor calibration every 3 months
  • โœ… Monitor battery/solar panel performance weekly
  • โœ… Adjust thresholds seasonally based on crop needs
  • โœ… Implement predictive maintenance for valves
  • โœ… Consider expanding to additional fields

Future Enhancements

  • ๐Ÿ“ท Add camera-based plant health monitoring
  • ๐Ÿงช Integrate NPK (Nitrogen, Phosphorus, Potassium) sensors
  • ๐Ÿค– Implement machine learning for predictive irrigation
  • ๐Ÿ“ก Expand coverage with mesh network
  • โ˜๏ธ Add weather forecast integration

๐Ÿ“ Data Export

#install.packages("readr")  
library(readr)
# Export data to CSV
write_csv(iot_data, "iot_data.csv")

# Create summary report
summary_report <- tibble(
  Metric = c("Duration", "Total Readings", "Efficiency Score", 
             "Water Used", "ROI Period"),
  Value = c(
    paste(DURATION_DAYS, "days"),
    TOTAL_READINGS,
    paste0(round(efficiency_score, 1), "%"),
    paste0(round(water_used, 1), " liters"),
    paste0(round(roi_months, 1), " months")
  )
)

write_csv(summary_report, "summary.csv")

๐Ÿ“ž Contact & Repository

Information